import * as THREE from "three";
import { Group, Object3D, PlaneGeometry } from "three";
export module MyAtlas {
    class Rect {
        x: number = 0;
        y: number = 0;
        w: number = 0;
        h: number = 0;
    }
    export class Atlas {
        maps: { [id: string]: Rect } = {};
        tex: THREE.Texture;
        texwidth: number = 0;
        texheight: number = 0;
        unit: number = 1;
        loaded?: (at: Atlas) => void;
        mapElem: { [id: string]: PlaneGeometry } = {};
        constructor(loader: THREE.TextureLoader, urljson: string, urltex: string, unit: number, callback?: (at: Atlas) => void) {
            this.tex = loader.load(urltex);
            this.loaded = callback;
            this.load(urljson);
        }
        async load(urljson: string): Promise<void> {

            let json = JSON.parse(await (await fetch(urljson)).text());
            this.texwidth = json["meta"]["size"]["w"];
            this.texheight = json["meta"]["size"]["h"];
            let frames = json["frames"];
            for (let key in frames) {
                let name = key;
                let dotpos = key.lastIndexOf(".");
                if (dotpos >= 0) {
                    name = key.substr(0, dotpos);
                }
                this.maps[name] = frames[key]["frame"] as Rect;
                console.log("name=" + key);
            }
            if (this.loaded)
                this.loaded(this);
        }
        //拓展一下atlas，复用spriteMesh
        GetSpriteMesh(name: string): PlaneGeometry {
            var sprite = this.mapElem[name];
            if (sprite == undefined) {
                var rect = this.maps[name];
                sprite = new THREE.PlaneGeometry(rect.w / this.unit, rect.h / this.unit);
                var uv = sprite.getAttribute("uv");
                var l = rect.x;
                var r = rect.x + rect.w;
                var t = this.texheight - rect.y;
                var b = this.texheight - rect.y - rect.h;
                uv.setXY(0, l / this.texwidth, t / this.texheight);//左上
                uv.setXY(1, r / this.texwidth, t / this.texheight);//右上
                uv.setXY(2, l / this.texwidth, b / this.texheight);//左下
                uv.setXY(3, r / this.texwidth, b / this.texheight);//右下

                this.mapElem[name] = sprite;
            }
            return sprite;
        }

        CreatePlaneMesh(name: string): THREE.Mesh {
            var sprite = this.GetSpriteMesh(name);

            let elem = new THREE.Mesh(sprite, new THREE.MeshBasicMaterial(
                { map: this.tex, transparent: true }
            ));
            return elem;
        }
    }
    export class Frameinfo {
        constructor(geom: PlaneGeometry, delay: number) {
            this.geom = geom;
            this.delay = delay;
        }
        geom: PlaneGeometry;
        delay: number;
    }
    export class AniObj extends THREE.Mesh {
        frames: Frameinfo[] = [];
        curfid: number = 0;
        timer: number = 0;
        clock: THREE.Clock = new THREE.Clock();
        constructor(at: Atlas) {
            super();

            this.material = new THREE.MeshBasicMaterial(
                { map: at.tex, transparent: true });


        }
        updateMatrix() {
            super.updateMatrix();
            if (this.frames.length == 0)
                return;
            //this.timer += 0.016;
            //每个临时对象用一个clock太奢侈了，全世界公用一个clock就行了，以后处理
            var delta = this.clock.getDelta();//
            if (delta > 0.3)//限制delta，避免突然的卡顿造成动画追赶
                delta = 0.3;
            this.timer += delta
            var cf = this.frames[this.curfid];
            if (this.timer > cf.delay) {
                this.timer -= cf.delay;
                this.curfid++;
                if (this.curfid >= this.frames.length)
                    this.curfid = 0;
            }

            this.geometry = cf.geom;
        }

    }
}
